/*
 * @Author: lixingyu liangwu.lxy@foxmail.com
 * @Date: 2023-05-06 22:07:08
 * @LastEditors: lixingyu liangwu.lxy@foxmail.com
 * @LastEditTime: 2023-05-06 23:04:47
 * @FilePath: /tiny-coroutine/core/tyco_coroutine.h
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef __TYCO_COROUTINE_H__
#define __TYCO_COROUTINE_H__

#define _USE_UCONTEXT

#ifdef _USE_UCONTEXT
#include <ucontext.h>
#endif // _USE_UCON

#include <stdlib.h>
#include <sys/epoll.h>
#include <pthread.h>
#include "queue.h"
#include "rbtree.h"
#include "type.h"


#define TYCO_CO_STACKSIZE_MAX	(128*1024) // {http: 16*1024, tcp: 4*1024}
#define TYCO_EVENT_ARRAY_SIZE_MAX	1024

#define BIT(x)				(1 << (x))
#define CLEARBIT(x) 		~(1 << (x))

typedef enum _tyco_coroutine_status {
	TYCO_COROUTINE_STATUS_NEW,
	TYCO_COROUTINE_STATUS_WAIT_READ,
	TYCO_COROUTINE_STATUS_WAIT_WRITE,
	TYCO_COROUTINE_STATUS_SLEEP,
	TYCO_COROUTINE_STATUS_READY,
	TYCO_COROUTINE_STATUS_RUN,
	TYCO_COROUTINE_STATUS_EXITED,
	TYCO_COROUTINE_STATUS_FDEOF,			// 表示在进行文件操作时达到了文件结尾
	TYCO_COROUTINE_STATUS_DETACH,
} tyco_coroutine_status;

typedef void (*proc_coroutine)(void *);



typedef struct _tyco_coroutine {
	time_t birth;
	time_t runtime;
	uint64_t id;
	tyco_coroutine_status status;
	time_t sleep_usecs;

	struct _tyco_schedule *sched;
	void *stack;
	size_t stack_size;

	uint32_t ops;		// ????

	int fd;
	uint16_t 	events;

#ifdef _USE_UCONTEXT
	ucontext_t ctx;
#else
	nty_cpu_ctx ctx;
#endif // _USE_UCONTEXT
	proc_coroutine func;
	void *arg;
	void *data;


} tyco_coroutine;





typedef struct _tyco_schedule {
	time_t	birth;

	int epoller_fd;
	int eventfd;		// 生产者消费者
	struct epoll_event eventArray[TYCO_EVENT_ARRAY_SIZE_MAX];	// get epoll events in epoll_wait
	int liveEventNums;		// 当前活跃的ep事件个数

	int num_new_events;		// 等待事件 --> 就绪

#ifdef _USE_UCONTEXT
	ucontext_t ctx;
#else
	nty_cpu_ctx ctx;
#endif // _USE_UCONTEXT
	void *stack;			// 暂存切换函数的栈的基地址
	size_t stack_size;		// 栈大小 (=rbp-rsp)
	size_t page_size;		// the system's page size
	struct _tyco_coroutine *curr_thread;

	struct queue 	*ready;
	struct rbtree 	*sleep;
	struct rbtree 	*wait;


} tyco_schedule;


extern int tyco_coroutine_yield(tyco_coroutine *co);
extern int tyco_coroutine_resume(tyco_coroutine *co);


extern pthread_key_t GLOBAL_SCHED_KEY;
extern inline tyco_schedule* tyco_get_sched(void);


#endif // !__TYCO_COROUTINE_H__